﻿using Microsoft.Extensions.DependencyInjection;
using QPlcPlayer.Models;
using QPlcPlayer.Services;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Entity.Infrastructure.Interception;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Net.Mime.MediaTypeNames;

namespace QPlcPlayer
{
	public partial class MainForm : Form
	{

		private System.Timers.Timer timer_jiemian;
		private System.Timers.Timer timer_huankong;
		private System.Timers.Timer timer_plc;
		private System.Timers.Timer timer_plc_cache;


		private AgvCar Car;
		private DosingSchedule DosingSchedule;
		private int PigeonCageCount;
		private int PigeonCageOK = 0;


		private DateTime first_time;
		private DateTime second_time;
		private DateTime third_time;

		
		private DateTime get_first_time()
		{
			if (first_time.Year<2000||first_time == null)
			{
				var schedule = AppRuntime.GetDosingSchedule();
				var firstTime = DateTime.Parse($"{schedule.HourFirst}:{schedule.MinuteFirst}:00");
				first_time = firstTime;
				
				

			}
			return first_time;
		}
		private DateTime get_second_time()
		{
			if (second_time.Year<=2000||second_time == null)
			{
				var schedule = AppRuntime.GetDosingSchedule();
				var secondTime = DateTime.Parse($"{schedule.HourSecond}:{schedule.MinuteSecond}:00");
				second_time = secondTime;
			}
			return second_time;
		}

		private DateTime get_third_time()
		{
			if(third_time.Year<=2000||third_time == null)
			{
				var schedule = AppRuntime.GetDosingSchedule();
				var thirdTime = DateTime.Parse($"{schedule.HourThird}:{schedule.MinuteThird}:00");
				third_time = thirdTime;
			}
			return third_time;
		}

		public MainForm()
		{
			InitializeComponent();

			var nowstr = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
			label11.Text = nowstr;
			Task.Run(() =>
			{
				UpdateFormData();

			});
			AppRuntime.TodayDosingSchedule = AppRuntime.GetService().GetService<DosingScheduleService>().GetTodayDosingSchedulePlus();
			var QTimerStatus = AppRuntime.GetService().GetService<QTimerStatusService>().GetQTimerStatus(AppRuntime.CarNumber)??new Models.QTimerStatus();
			timer_jiemian = new System.Timers.Timer();
			timer_jiemian.Elapsed += timer_jiemian_Tick;
			timer_jiemian.Interval = double.Parse(QTimerStatus.Interval_Timer_JieMian.ToString());

			timer_huankong = new System.Timers.Timer();
			timer_huankong.Elapsed += timer_huankong_Tick;
			timer_huankong.Interval = double.Parse(QTimerStatus.Interval_Timer_HuanKong.ToString());

			timer_plc = new System.Timers.Timer();
			timer_plc.Elapsed += UpdatePLCTimer_Tick;
			timer_plc.Interval = double.Parse(QTimerStatus.Interval_Timer_PLC.ToString()); 
			timer_plc_cache = new System.Timers.Timer();
			timer_plc_cache.Elapsed += UpdatePLC_Cache_Tick;
			timer_plc_cache.Interval = double.Parse((QTimerStatus.MinuteBeforeFeed*60*1000).ToString());

		}

		private void UpdateFormData()
		{
			var car = AppRuntime.GetService().GetService<AgvCarService>().GetAgvCarByNumber(AppRuntime.CarNumber) ?? new Models.AgvCar();
			var dosingSchedule = AppRuntime.GetService().GetService<DosingScheduleService>().GetDosingScheduleByCarId(car.ID);
			Car = car;
			DosingSchedule = dosingSchedule;
			PigeonCageCount = AppRuntime.GetService().GetService<PigeonCageService>().GetPigeonCageCount();
			if (label8.InvokeRequired)
			{
				label8.Invoke(new MethodInvoker(delegate
				{
					label8.Text = PigeonCageCount.ToString();
				}));
			}
			else
			{
				label8.Text = PigeonCageCount.ToString();
			}

			if (lblFirstTime.InvokeRequired)
			{
				lblFirstTime.Invoke(new MethodInvoker(delegate
				{
					lblFirstTime.Text = $"{dosingSchedule.HourFirst.ToString("D2")}:{dosingSchedule.MinuteFirst.ToString("D2")}";
				}));

			}
			else
			{
				lblFirstTime.Text = $"{dosingSchedule.HourFirst.ToString("D2")}:{dosingSchedule.MinuteFirst.ToString("D2")}";
			}

			if (lblSecondTime.InvokeRequired)
			{
				lblSecondTime.Invoke(new MethodInvoker(delegate
				{
					lblSecondTime.Text = $"{dosingSchedule.HourSecond.ToString("D2")}:{dosingSchedule.MinuteSecond.ToString("D2")}";
				}));
			}
			else
			{
				lblSecondTime.Text = $"{dosingSchedule.HourSecond.ToString("D2")}:{dosingSchedule.MinuteSecond.ToString("D2")}";
			}

			if (lblThirdTime.InvokeRequired)
			{
				lblSecondTime.Invoke(new MethodInvoker(delegate
				{
					lblThirdTime.Text = $"{dosingSchedule.HourThird.ToString("D2")}:{dosingSchedule.MinuteThird.ToString("D2")}";
				}));
			}
			else
			{
				lblThirdTime.Text = $"{dosingSchedule.HourThird.ToString("D2")}:{dosingSchedule.MinuteThird.ToString("D2")}";
			}




		}


		private void 设置IPToolStripMenuItem_Click(object sender, EventArgs e)
		{
			var form = new SettingIPForm();

			form.ShowDialog(this);
		}

		private void 测试PLCToolStripMenuItem_Click(object sender, EventArgs e)
		{
			var form = new TestPLCForm();
			form.ShowDialog(this);
		}

		private void MainForm_Load(object sender, EventArgs e)
		{

		}


		private void 更新数据ToolStripMenuItem_Click(object sender, EventArgs e)
		{
			//更新喂料时间
			UpdateFormData();

		}

		private void timer_jiemian_Tick(object sender, EventArgs e)
		{

			var nowstr = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
			if (label11.InvokeRequired)
			{
				label11.Invoke(new MethodInvoker(delegate
				{
					label11.Text = nowstr;
				}));
			}
			else
			{
				label11.Text = nowstr;
			}

			if (label9.InvokeRequired)
			{
				label9.Invoke(new MethodInvoker(() =>
				{
					label9.Text = PigeonCageOK.ToString();
				}));
			}
			else
			{
				label9.Text = PigeonCageOK.ToString();
			}

			if (DosingSchedule == null) return;
			var nowHour = DateTime.Now.Hour;
			TimeSpan sp;
			var firststr = $"{DosingSchedule.HourFirst.ToString("D2")}:{DosingSchedule.MinuteFirst.ToString("D2")}";
			var first_date =get_first_time();			
			var second_date =get_second_time();
			var third_date =get_third_time();



			if (nowHour <=DosingSchedule.HourFirst && DateTime.Now<=first_date)
			{
				
				sp =first_date  - DateTime.Now;
			}
			else if (nowHour <= DosingSchedule.HourSecond && DateTime.Now<=second_date)
			{
				
				sp = second_date - DateTime.Now;
			}
			else if (nowHour <= DosingSchedule.HourThird && DateTime.Now<=third_date)
			{
			
				sp =third_date - DateTime.Now;
			}
			else
			{
				
				var nextDate = DateTime.Parse(firststr).AddDays(1);
				sp = nextDate - DateTime.Now;

			}
			var hours = sp.Hours;
			var minutes = sp.Minutes;
			var seconds = sp.Seconds;

			if (label5.InvokeRequired)
			{
				label5.Invoke(new MethodInvoker(() =>
				{
					label5.Text = $"{hours}小时{minutes}分钟{seconds}秒";
				}));
			}
			else
			{
				label5.Text = $"{hours}小时{minutes}分钟{seconds}秒";
			}
			if (label9.InvokeRequired)
			{
				label9.Invoke(new MethodInvoker(() =>
				{
					label9.Text = PigeonCageOK.ToString();
				}));
			}
			else
			{
				label9.Text = PigeonCageOK.ToString();
			}


			


		}


		private void timer_huankong_Tick(object sender, EventArgs e)
		{


			//更新AGV小车的状态及用电量
			try
			{
				var carStatus = CarStatus.DaiJi;
				var isTrobule = AppRuntime.GetPlcManager().前有障碍物();
				if (isTrobule) carStatus = CarStatus.Trouble;
				var isWeiLiao = AppRuntime.GetPlcManager().喂料中();
				if (isWeiLiao) carStatus = CarStatus.WeiLiao;
				var electricity = AppRuntime.GetPlcManager().当前电量();
				AppRuntime.GetService().GetService<AgvCarService>().UpdateCarInfo(AppRuntime.CarNumber, carStatus, electricity);

			}
			catch (Exception ex)
			{
				AppRuntime.Logger_Error(ex.Message);
			}



		}

		private DateTime ZeroTime = new DateTime(1, 1, 1);
		private void UpdatePLC_Cache_Tick(object sender, EventArgs e)
		{
			try
			{
				var schedule = AppRuntime.GetDosingSchedule();
				var firstTime = DateTime.Parse($"{schedule.HourFirst}:{schedule.MinuteFirst}:00");
				var secondTime = DateTime.Parse($"{schedule.HourSecond}:{schedule.MinuteSecond}:00");
				var thirdTime = DateTime.Parse($"{schedule.HourThird}:{schedule.MinuteThird}:00");
				var interval = Double.Parse((AppRuntime.QTimerStatus.MinuteBeforeFeed * 1000 * 60).ToString())*2;
			
				var span_first=DateTime.Now-firstTime;
				if(span_first.TotalMilliseconds>0 && span_first.TotalMilliseconds <= interval)
				{
					AppRuntime.TodayDosingSchedule= AppRuntime.GetService().GetService<DosingScheduleService>().GetTodayDosingSchedulePlus();
					AppRuntime.PLCCache.Clear();
					first_time = ZeroTime;
					return;
				}
				var span_second=DateTime.Now-secondTime;
				if(span_second.TotalMilliseconds>0 && span_second.TotalMilliseconds <= interval)
				{
					AppRuntime.TodayDosingSchedule = AppRuntime.GetService().GetService<DosingScheduleService>().GetTodayDosingSchedulePlus();
					AppRuntime.PLCCache.Clear();
					second_time = ZeroTime;
					return;
				}
				var span_third=DateTime.Now-thirdTime;
				if (span_third.TotalMilliseconds > 0 && span_third.TotalMilliseconds <= interval)
				{
					AppRuntime.TodayDosingSchedule = AppRuntime.GetService().GetService<DosingScheduleService>().GetTodayDosingSchedulePlus();
					AppRuntime.PLCCache.Clear();
					third_time = ZeroTime;
					return;
				}



			}
			catch(Exception ex)
			{
				AppRuntime.Logger_Error(ex.Message);
			}
		}


		public double m_interval = Double.Parse((AppRuntime.QTimerStatus.Interval_Timer_PLC).ToString()) * 5;


		public static object m_lock_obj = new object();
		//定时操作plc定时器
		private void UpdatePLCTimer_Tick(object sender, EventArgs e)
		{
			try
			{
				lock (m_lock_obj)
				{
					
					var firstTime = get_first_time();
					var secondTime = get_second_time();
					var thirdTime = get_third_time();

					var isfirst = DateTime.Now >= firstTime && DateTime.Now <= secondTime;
					var issecond = DateTime.Now >= secondTime && DateTime.Now <= thirdTime;
					var isthird = DateTime.Now >= thirdTime;
					var totalMilliseconds_first = (DateTime.Now - firstTime).TotalMilliseconds;
					var totalMilliseconds_second = (DateTime.Now - secondTime).TotalMilliseconds;
					var totalMilliseconds_third = (DateTime.Now - thirdTime).TotalMilliseconds;

					var is_ok_first = totalMilliseconds_first >= 0 && totalMilliseconds_first <= m_interval;
					var is_ok_second = totalMilliseconds_second >= 0 && totalMilliseconds_second <= m_interval;
					var is_ok_third = totalMilliseconds_third >= 0 && totalMilliseconds_third <= m_interval;
					if (is_ok_first || is_ok_second || is_ok_third)
					{

						AppRuntime.GetPlcManager().上位机下达允许喂料(true);
						if (AppRuntime.KKSchedule.Count <= 0) AppRuntime.InitKKSchedule();
						return;
					}

					if (isfirst || issecond || isthird)
					{
						var res = AppRuntime.InteractionPLC(isfirst, issecond, isthird);
						if (res.IsOK)
						{
							PigeonCageOK += 1;
						}
						
					}
				}
			}
			catch (Exception ex)
			{
				AppRuntime.Logger_Error(ex.Message);
			}


		}

		private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
		{
			e.Cancel = true;
			this.Hide();
		}

		private void ShowtoolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (this.ShowInTaskbar)
			{
				this.Show();
			}
		}

		private void closetoolStripMenuItem_Click(object sender, EventArgs e)
		{
			this.Close();
			this.Dispose();
		}

		private void 设置喂料信息ToolStripMenuItem_Click(object sender, EventArgs e)
		{
			var frm = new SettingFeedFrm();
			frm.ShowDialog();
		}

		private void 定时器设置ToolStripMenuItem_Click(object sender, EventArgs e)
		{
			var frm = new QTimerFrm();
			frm.ShowDialog();
		}

		private void 手动启动喂料ToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (timer_plc.Enabled) timer_plc.Stop();
			if (timer_plc_cache.Enabled) timer_plc_cache.Stop();
			if (timer_huankong.Enabled) timer_huankong.Stop();
			if (timer_jiemian.Enabled) timer_jiemian.Stop();
			var QTimerStatus = AppRuntime.GetService().GetService<QTimerStatusService>().GetQTimerStatus(AppRuntime.CarNumber) ?? new Models.QTimerStatus();
			AppRuntime.QTimerStatus = QTimerStatus;
			if (QTimerStatus.IsTimer_PLC)
			{
				timer_plc.Interval =double.Parse( QTimerStatus.Interval_Timer_PLC.ToString());
				timer_plc.Start();
				timer_plc_cache.Interval= double.Parse((QTimerStatus.MinuteBeforeFeed*60*1000).ToString());
				timer_plc_cache.Start();
			}
			if (QTimerStatus.IsTimer_HuanKong)
			{
				timer_huankong.Interval= double.Parse(QTimerStatus.Interval_Timer_HuanKong.ToString());
				timer_huankong.Start();
			}
			if (QTimerStatus.IsTimer_JieMian)
			{
				timer_jiemian.Interval = double.Parse(QTimerStatus.Interval_Timer_JieMian.ToString());
				timer_jiemian.Start();
			}


		}
	}
}
